/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "单数值计算.h"

#include "Context/数据转换.h"

#include "节点/插座/通用插座.h"
#include "节点/socket_utils.h"
#include "节点/节点树.h"
#include "运算符.h"
#include "节点数据声明.h"



template<typename T1, typename T2, typename T3>
void f_一元计算(T1* outData, T2* inDataA, T3* inDataB, uint32 运算符) {
	switch (运算符) {
	case 0: (*outData) = (*inDataA) + (*inDataB); break;
	case 1: (*outData) = (*inDataA) - (*inDataB); break;
	case 2: (*outData) = (*inDataA) * (*inDataB); break;
	case 3: (*outData) = (*inDataA) / (*inDataB); break;
	}

	/*switch (运算符) {
	case E_运算符::e_逻辑_非:
	case E_运算符::e_位运算_取反: {
		//float32* inDataB = ((float32*)数据2.m_Data);
		//f_切换运算符<float32, float32>(this, outData, inDataA, 1, inDataB, 1, E_运算符(方式));
		float32 a = 0;
		a = !(-1.0);
		break;
	}
	case E_运算符::e_算数运算_加: (*outData) = (*inDataA) + (*inDataB); break;
	case E_运算符::e_算数运算_减: (*outData) = (*inDataA) - (*inDataB); break;
	case E_运算符::e_算数运算_乘: (*outData) = (*inDataA) * (*inDataB); break;
	case E_运算符::e_算数运算_除: (*outData) = (*inDataA) / (*inDataB); break;
	}*/
}





template<typename T1, typename T2, typename F>
void f_计算(std::vector<T1>& outData, std::vector<T1>& dataA, std::vector<T2>& dataB, F vec_func) {
	uint64 num = dataA.size();


	outData.resize(num);
	T1* p_do = outData.data();
	T1* p_d1 = dataA.data();
	T2* p_d2 = dataB.data();



	if (dataB.size() >= num) {
		for (int64 i = 0; i < num; ++i) {
			p_do[i] = vec_func(p_d1[i], p_d2[i]);
		}
	}
	else {
		for (int64 i = 0; i < num; ++i) {
			p_do[i] = vec_func(p_d1[i], p_d2[0]);
		}
	}

}






template<typename T1, typename T2>
void f_切换运算符(C_单值计算节点* node, T1* p_outData, T1* p_dataA, uint64 A_num, T2* p_dataB, uint64 B_num, E_运算符 运算符) {
	
	switch (运算符)
	{
	case E_运算符::e_逻辑_非: {
		f_一元计算<T1>(p_outData, p_dataA, A_num, 运算符);
		break;
	}
	default:
		break;
	}

}




C_单值计算节点::C_单值计算节点(S_设备环境& ctx) : C_节点基类(DEF_单值计算节点) {
	m_Ctx = ctx;
	m_Name = L"计算";

	C_插座基类* socket;
	DEF_创建F32插座_I(L"源1", nullptr);
	DEF_创建F32插座_I(L"源2", nullptr);
	
	DEF_创建F32插座_O(L"out", nullptr);


	m_计算方式 = f_alloc_EnumProp(nullptr, {
		//	0			1			2			
		//{ {L"!", ""}, {L"~", ""}, {L"++", "++"},  {L"--", "--"},
		//	3			4				5	
		//{L"后++", ""}, {L"后--", ""}, {L"sizeof", ""},
		//	0			1			2			3		
		{L"+", ""}, {L"-", ""}, {L"*", ""}, {L"/", ""}, 
		//	4			5
		{L"<<", ""}, {L">>", ""}, 
		//	11			12			13			14			
		//{L"<", ""}, {L"<=", ""}, {L">", ""}, {L">=", ""}, 
		//	15			16
		//{L"==", ""}, {L"!=", ""},
		//	17			18				19				20				21
		//{L"&", ""}, {L"^", ""}, {L"|", ""}, {L"&&", ""}, {L"||", ""}, { L"?", "" },
		//	22			23			24			25			26				27				28				29				30			31				32
		//{L"=", ""}, {L"+=", ""}, {L"-=", ""}, {L"*=", ""}, {L"/=", ""}, { L"%=", "" }, { L"<<=", "" }, { L">>=", "" }, { L"&=", "" }, { L"^=", "" }, { L"|=", "" }

		//	22			23			24			25			26				27				28				29				30			31				32
		//{L"=", ""}, {L"+=", ""}, {L"-=", ""}, {L"*=", ""}, {L"/=", ""}, { L"%=", "" }, { L"<<=", "" }, { L">>=", "" }, { L"&=", "" }, { L"^=", "" }, { L"|=", "" }

		},
		L"计算方式",
		0,
		nullptr
	);
	m_计算方式.m_私有 = true;

	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(1));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(2));
	f_构建代码_分配渲染器GPU属性变量(m_计算方式);

}

C_单值计算节点::~C_单值计算节点() {
	f_prop_Release(m_计算方式);
	//f_prop_Release(m_是否改变原数据);
	//f_prop_Release(m_执行代码);
}

#define _DEF_计算两向量标量节点_插座类型转换_                                                     \
创建数组 = socket1->f_get接入的数据类型() == E_值类型::e_Type_Vec3_1D ||                          \
                 socket2->f_get接入的数据类型() == E_值类型::e_Type_F32_1D;                       \
if (!创建数组 || (!socket1->f_isLink() && !socket2->f_isLink()) ) {                               \
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_Vec3);           \
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Vec3);           \
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);            \
	创建数组 = false;                                                                             \
}                                                                                                 \
else {                                                                                            \
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_Vec3_1D);        \
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Vec3_1D);        \
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32_1D);         \
	创建数组 = true;                                                                              \
}                                                                                                 \
socket1 = f_get输入插座(1);                                                                       \
socket2 = f_get输入插座(2);  

bool C_单值计算节点::f_update() {
	C_插座基类* inSocket1 = f_get输入插座(1);
	C_插座基类* inSocket2 = f_get输入插座(2);

	bool 创建数组 = false;
	switch (inSocket1->f_get接入的数据类型()) {
		case E_值类型::e_Type_I8_1D:
		case E_值类型::e_Type_I32_1D:
		case E_值类型::e_Type_UI32_1D:
		case E_值类型::e_Type_F32_1D:
			创建数组 = true;
			break;
	}
	switch (inSocket2->f_get接入的数据类型()) {
		case E_值类型::e_Type_I8_1D:
		case E_值类型::e_Type_I32_1D:
		case E_值类型::e_Type_UI32_1D:
		case E_值类型::e_Type_F32_1D:
			创建数组 = true;
			break;
	}

	if (!inSocket1->f_isLink() && !inSocket2->f_isLink()) {
		创建数组 = false;
	}

	if (创建数组) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32_1D);
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);
	}
	inSocket1 = f_get输入插座(1);
	inSocket2 = f_get输入插座(2);


	if (创建数组) {
		auto 数据1 = DEF_F32插座_1D数据(inSocket1, 0);
		auto 数据2 = DEF_F32插座_1D数据(inSocket2, 0);
		E_运算符 方式 = E_运算符(f_prop_enum(m_计算方式));

		uint32 num = DEF_Max(数据1->count, 数据2->count);
		auto* outData = DEF_F32插座_1D数据(f_get输出插座(1));
		f_core_array_resize((S_Array*)outData, num);

		bool 多例1 = 数据1->count >= num;
		bool 多例2 = 数据2->count >= num;
		for (uint32 i = 0; i < num; ++i) {
			float32* a;
			float32* b;
			float32* c;

			if(多例1) a = &(数据1->ptr_userData[i]);
			else a = &(数据1->ptr_userData[0]);

			if(多例2) b = &(数据2->ptr_userData[i]);
			else b = &(数据2->ptr_userData[0]);

			f_一元计算(&outData->ptr_userData[i], a, b, f_prop_enum(m_计算方式));
		}
	}
	else {
		


		auto 数据1 = DEF_F32插座数据(inSocket1, 0);
		auto 数据2 = DEF_F32插座数据(inSocket2, 0);
		E_运算符 方式 = E_运算符(f_prop_enum(m_计算方式));

		auto& outData = DEF_F32插座数据(f_get输出插座(1));

		f_一元计算(&outData, &数据1, &数据2, f_prop_enum(m_计算方式));
	}

	return false;
}

std::string C_单值计算节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";
	bool 创建数组 = false;
	bool 创建浮点 = false;
	std::string name = f_getName();



	C_插座基类* inSocket1 = f_get输入插座(1);
	C_插座基类* inSocket2 = f_get输入插座(2);

	

	auto* rt = f_getThis节点树();
	if (rt->m_树类型 == E_节点树类型::e_type_着色节点树) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);
		inSocket1 = f_get输入插座(1);
		inSocket2 = f_get输入插座(2);

		m_Code += inSocket1->f_构建变量代码(0);
		m_Code += inSocket2->f_构建变量代码(0);

		bool 浮点数 = false;
		switch (inSocket1->m_Type) {
		case E_值类型::e_Type_F32:
			if (inSocket1->m_GPU缓存.m_Buf) {
				f_buf_F32_at(inSocket1->m_GPU缓存) = DEF_F32插座数据(inSocket1);
			}
		case E_值类型::e_Type_F64:
			浮点数 = true;
			break;
		}

		switch (inSocket2->m_Type) {
		case E_值类型::e_Type_F32:
			if (inSocket2->m_GPU缓存.m_Buf) {
				f_buf_F32_at(inSocket2->m_GPU缓存) = DEF_F32插座数据(inSocket2);
			}
		case E_值类型::e_Type_F64:
			浮点数 = true;
			break;
		}

		((int32*)m_计算方式.m_GPU缓存[0].m_Buf->m_mappedPtr)[m_计算方式.m_GPU缓存[0].m_Mem.m_偏移] = f_prop_enum(m_计算方式);



		if (浮点数) {
			m_Code += "float " + name + " = 0;\n";
		}
		else {
			m_Code += "int " + name + " = 0;\n";
		}

		m_Code += "switch(" + f_代码构建_属性变量(m_计算方式, rt) + "){\n";

		m_Code += "case 0:\n";
		m_Code += name + " = " + inSocket1->f_getCode(0) + " + " + inSocket2->f_getCode(0) + ";\n";
		m_Code += "break;\n";

		m_Code += "case 1:\n";
		m_Code += name + " = " + inSocket1->f_getCode(0) + " - " + inSocket2->f_getCode(0) + ";\n";
		m_Code += "break;\n";

		m_Code += "case 2:\n";
		m_Code += name + " = " + inSocket1->f_getCode(0) + " * " + inSocket2->f_getCode(0) + ";\n";
		m_Code += "break;\n";

		m_Code += "case 3:\n";
		m_Code += name + " = " + inSocket1->f_getCode(0) + " / " + inSocket2->f_getCode(0) + ";\n";
		m_Code += "break;\n";

		m_Code += "}\n";

	}
	else {
		std::string 数量[2];

		auto 接入的数据类型1 = inSocket1->f_get接入的数据类型();
		auto 接入的数据类型2 = inSocket2->f_get接入的数据类型();

		if (!inSocket1->f_isLink() && !inSocket2->f_isLink()) {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);

			inSocket1 = f_get输入插座(1);
			inSocket2 = f_get输入插座(2);
			创建数组 = false;
		}
		else {
			switch (inSocket1->f_get接入的数据类型()) {
				case E_值类型::e_Type_I8_1D:
				case E_值类型::e_Type_I32_1D:
				case E_值类型::e_Type_UI32_1D:
				case E_值类型::e_Type_F32_1D:
					创建数组 = true;
					break;
			}

			switch (inSocket2->f_get接入的数据类型()) {
				case E_值类型::e_Type_I8_1D:
				case E_值类型::e_Type_I32_1D:
				case E_值类型::e_Type_UI32_1D:
				case E_值类型::e_Type_F32_1D:
					创建数组 = true;
					break;
				default:
					break;
			}
		}


		
		


		if (创建数组) {
			if (f_代码构建_是否为单值浮点(接入的数据类型1) || f_代码构建_是否为单值浮点(接入的数据类型2)) {
				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32_1D);
				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32_1D);

				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32_1D);

				创建浮点 = true;
			}
			else {
				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_I32_1D);
				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I32_1D);

				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I32_1D);
			}
		}
		else {
			if (f_代码构建_是否为单值浮点(接入的数据类型1) || f_代码构建_是否为单值浮点(接入的数据类型2)) {
				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);

				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);

				创建浮点 = true;
			}
			else {
				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_I32);
				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I32);

				f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I32);
			}
			
		}
		inSocket1 = f_get输入插座(1);
		inSocket2 = f_get输入插座(2);
			
		std::string 运算类型代码 = f_代码构建_属性变量(m_计算方式, rt);

		if (创建数组) {
			if (创建浮点) {
				m_Code += "S_F32Array* " + name + ";\n";
			}
			else {
				m_Code += DEF_S(S_I32Array*)" " + name + ";\n";
			}
			
		}
		else {
			if (创建浮点) {
				m_Code += "float32 " + name + ";\n";
			}
			else {
				m_Code += "int32 " + name + ";\n";
			}
		}

		
		m_Code += "{\n";


		m_Code += inSocket1->f_构建变量代码(0);
		m_Code += inSocket2->f_构建变量代码(0);

		if (创建数组) {
			if (创建浮点) {
				m_Code += name + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, "1") + ";\n";
				m_Code += DEF_S(f_JIT_Fun_F32s_c_F32s);
				m_Code += "(" + name + ", " + inSocket1->f_getCode(0) + ", " + inSocket2->f_getCode(0) + ", " + 运算类型代码 + ");\n";
			}
			else {
				m_Code += name + " = " + f_代码构建_创建Array(E_值类型::e_Type_I32_1D, "1") + ";\n";
				m_Code += DEF_S(f_JIT_单值数组计算);
				m_Code += "(" + name + ", " + inSocket1->f_getCode(0) + ", " + inSocket2->f_getCode(0) + ", " + 运算类型代码 + ");\n";
			}
		}
		else {
			if (创建浮点) {
				m_Code += "auto* 参数A指针 = &" + inSocket1->f_getCode(0) + ";\n";
				m_Code += "auto* 参数B指针 = &" + inSocket2->f_getCode(0) + ";\n";
				m_Code += name + " = " + DEF_S(f_JIT_Fun_f_c_f)"(参数A指针, 参数B指针, " + 运算类型代码 + "); \n";
			}
			else {
				m_Code += "auto* 参数A指针 = &" + inSocket1->f_getCode(0) + ";\n";
				m_Code += "auto* 参数B指针 = &" + inSocket2->f_getCode(0) + ";\n";
				m_Code += name + " = " + DEF_S(f_JIT_单值整数计算)"(参数A指针, 参数B指针, " + 运算类型代码 + "); \n";
			}
		}
		
		m_Code += m_ReleaseCode;
		m_Code += "}\n";
	}

	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (创建数组) {
			m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(name);
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(name);
	}

	return m_Code;
}

void C_单值计算节点::f_getStr(std::vector<std::vector<std::wstring>>& 文本) {
	auto* outSocket1 = f_get输出插座(1);

	switch (outSocket1->m_Type) {
	case E_值类型::e_Type_I32:
	case E_值类型::e_Type_UI32:
	case E_值类型::e_Type_F32:
	case E_值类型::e_Type_F64: {
		auto outData = DEF_F32插座数据(f_get输出插座(1));
		std::vector<std::wstring> 输入(2);
		输入[0] = m_Name;
		输入[1] = f_浮点数值转宽字符串(outData);
		文本.push_back(输入);
		break;
	}

	case E_值类型::e_Type_I32_1D:
	case E_值类型::e_Type_UI32_1D:
	case E_值类型::e_Type_F32_1D: {
		auto outData = DEF_F32插座_1D数据(f_get输出插座(1));
		std::vector<std::wstring> 输入(1);
		输入[0] = m_Name;

		for (uint32 i = 0; i < outData->count; ++i) {
			输入.push_back(f_浮点数值转宽字符串(outData->ptr_userData[i]));
		}
		文本.push_back(输入);
		break;
	}
	default:
		break;
	}
	
}

void C_单值计算节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	f_prop_Load(m_计算方式, f);
}

void C_单值计算节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	f_prop_Save(m_计算方式, f);
}

//void C_单值计算节点::f_读取(FILE* f) {
//	C_节点基类::f_读取(f);
//	S_文件块 文件块 = f_file_读取文件块(f);
//	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
//		const uint8* 下一次读取数据指针 = 文件块.m_data;
//
//		下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
//	}
//	free(文件块.m_data);
//}
//
//void C_单值计算节点::f_写入(FILE* f) {
//	C_节点基类::f_写入(f);
//	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
//	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));
//
//	f_prop_Save(m_计算方式, 块);
//
//	文件块.m_data = 块->ptr_userData;
//	文件块.m_字节数 = 块->count;
//	f_file_保存文件块(f, 文件块);
//	f_core_array_free((S_Array*)块);
//}

void C_单值计算节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
	f_prop_enum(m_计算方式) = f_prop_enum(dynamic_cast<const C_单值计算节点*>(node)->m_计算方式);

	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);

	socket1->f_Copy(node->f_get输入插座(1));
	socket2->f_Copy(node->f_get输入插座(2));
}

C_节点基类* f_node_创建单值计算节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_单值计算节点(ctx);
}

C_节点基类* f_node_加载单值计算节点(S_设备环境& ctx, FILE* f){
	C_单值计算节点* node = new C_单值计算节点(ctx);
	//fread(&(((S_PropValueEnum*)node->m_计算方式.m_Value)->m_当前选项), sizeof(uint8), 1, f);
	//f_prop_Load(node->m_是否改变原数据, f);
	//f_prop_Load(node->m_执行代码, f);
	return node;
}

void f_node_保存单值计算节点(C_节点基类* n, FILE* f) {
	C_单值计算节点* node = dynamic_cast<C_单值计算节点*>(n);
	//fwrite(&(((S_PropValueEnum*)node->m_计算方式.m_Value)->m_当前选项), sizeof(uint8), 1, f);
	//f_prop_Save(node->m_是否改变原数据, f);
	//f_prop_Save(node->m_执行代码, f);
}



C_组合计算节点::C_组合计算节点(S_设备环境& ctx) : C_节点基类(DEF_单值计算节点) {
	m_Ctx = ctx;
	m_Name = L"计算";

	C_插座基类* socket;
	DEF_创建F32插座_I(L"源1", nullptr);
	DEF_创建F32插座_O(L"out", nullptr);

	f_get输入插座(1)->f_set多输入();

	m_计算方式 = f_alloc_EnumProp(nullptr, {
		//	0			1			2			3		
		{L"+", ""}, {L"*", ""}, {L"|", ""}, {L"&", ""},
		//	4			5
		{L"^", ""}, {L"||", ""}, {L"&&", ""},

							  },
							  L"计算方式",
							  0,
							  nullptr
							  );
	m_计算方式.m_私有 = true;

	m_是否改变原数据 = f_alloc_BoolProp(nullptr, L"改变原数据");
	m_计算方式.m_私有 = true;

	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(1));
	f_构建代码_分配渲染器GPU插座变量(*f_get输入插座(2));
	f_构建代码_分配渲染器GPU属性变量(m_计算方式);
}

C_组合计算节点::~C_组合计算节点() {
	f_prop_Release(m_是否改变原数据);
	f_prop_Release(m_计算方式);
}

bool C_组合计算节点::f_update() {
	auto* socket1 = f_get输入插座(1);
	uint32 链接数量 = socket1->f_getLinkNum();
	for (uint32 i = 0; i < 链接数量; ++i) {

	}
	return false;
}

std::string C_组合计算节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";
	bool 创建数组 = false;
	bool 创建浮点 = false;
	std::string name = f_getName();

	auto* socket1 = f_get输入插座(1);
	uint32 链接数量 = socket1->f_getLinkNum();

	
	for (uint32 i = 0; i < 链接数量; ++i) {
		auto 接入的数据类型1 = socket1->f_get接入的数据类型(i);

		if (f_代码构建_是否为数组(接入的数据类型1)) {
			创建数组 = true;
		}
		if (f_代码构建_是否为单值数组浮点(接入的数据类型1)) {
			创建浮点 = true;
		}
	}

	if (创建数组) {
		if (创建浮点) {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32_1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32_1D);

			m_Code += DEF_S(S_F32Array*)" " + name + " = " + f_代码构建_创建Array(E_值类型::e_Type_F32_1D, "1") + ";\n";
		}
		else {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_I32_1D);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I32_1D);

			m_Code += DEF_S(S_I32Array*)" " + name + " = " + f_代码构建_创建Array(E_值类型::e_Type_I32_1D, "1") + ";\n";
		}
	}
	else {
		if (创建浮点) {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);

			m_Code += DEF_S(float32)" " + name + ";\n";
		}
		else {
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_I32);
			f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I32);

			m_Code += DEF_S(int32)" " + name + ";\n";
		}
	}
	socket1 = f_get输入插座(1);


	auto socketIn = socket1->f_get链接到的输出插座();
	for (uint32 i = 0; i < 链接数量; ++i) {
		socket1->f_getCode(0);
	}


	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (创建数组) {
			m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(name);
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(name);
	}
	return m_Code;
}

void C_组合计算节点::f_getStr(std::vector<std::vector<std::wstring>>& 文本) {
}

void C_组合计算节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
	
		下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_组合计算节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_计算方式, 块);

	文件块.m_data = 块->ptr_userData;
	文件块.m_字节数 = 块->count;
	f_file_保存文件块(f, 文件块);
	f_core_array_free((S_Array*)块);
}

void C_组合计算节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
	const C_组合计算节点* 组合计算节点 = dynamic_cast<const C_组合计算节点*>(node);
	if (组合计算节点) {
		f_prop_enum(m_计算方式) = f_prop_enum(组合计算节点->m_计算方式);
		f_prop_enum(m_是否改变原数据) = f_prop_enum(组合计算节点->m_是否改变原数据);
	}
}

C_节点基类* f_node_创建组合计算节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_单值计算节点(ctx);
}

C_节点基类* f_node_加载组合计算节点(S_设备环境& ctx, FILE* f) {
	C_单值计算节点* node = new C_单值计算节点(ctx);
	return node;
}

void f_node_保存组合计算节点(C_节点基类* n, FILE* f) {
	C_单值计算节点* node = dynamic_cast<C_单值计算节点*>(n);
}




C_位运算节点::C_位运算节点(S_设备环境& ctx) : C_节点基类(DEF_位运算节点) {
	m_Ctx = ctx;
	m_Name = L"位运算";

	C_插座基类* socket;
	DEF_创建I32插座_I(L"a", nullptr);
	DEF_创建I32插座_I(L"b", nullptr);
	DEF_创建I32插座_O(L"c", nullptr);

	//f_get输入插座(1)->f_set多输入();
	m_计算方式 = f_alloc_EnumProp(nullptr, {
		//	0			1			2			3		
		{L"|", ""}, {L"&", ""}, {L"^", ""}, {L"<<", ""}, {L">>", ""}, 

							  },
							  L"计算方式",
							  0,
							  nullptr
							  );
	m_计算方式.m_私有 = true;

	m_是否改变原数据 = f_alloc_BoolProp(nullptr, L"改变原数据");
	m_是否改变原数据.m_私有 = true;
	f_prop_Bool(m_是否改变原数据) = false;
}

C_位运算节点::~C_位运算节点() {
	f_prop_Release(m_是否改变原数据);
	f_prop_Release(m_计算方式);
}

bool C_位运算节点::f_update() {
	return false;
}

std::string C_位运算节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";
	bool 创建数组 = false;
	bool 创建浮点 = false;
	std::string name = f_getName();


	auto* socket1 = f_get输入插座(1);
	uint32 链接数量 = socket1->f_getLinkNum();

	auto 接入的数据类型1 = socket1->f_get接入的数据类型(0);
	if (f_代码构建_是否为数组(接入的数据类型1)) {
		创建数组 = true;
	}
	if (f_代码构建_是否为单值数组浮点(接入的数据类型1)) {
		创建浮点 = true;
	}

	if (创建数组) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_UI32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_UI32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_UI32_1D);

		m_Code += DEF_S(S_UI32Array*)" " + name + " = " + f_代码构建_创建Array(E_值类型::e_Type_UI32_1D, "1") + ";\n";
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_UI32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_UI32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_UI32);

		m_Code += DEF_S(int32)" " + name + ";\n";
	}
	socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);


	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);
	auto 运算类型 = f_代码构建_属性变量(m_计算方式, f_getThis节点树());
	if (创建数组) {
		if (f_prop_Bool(m_是否改变原数据)) {
		}
		else {
			m_Code += DEF_S(f_JIT_位运算Um)"(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + name + ", " + 运算类型 + ");\n";
		}
	}
	else {
		if (f_prop_Bool(m_是否改变原数据)) {
			m_Code += DEF_S(f_JIT_位运算Uxx)"(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + 运算类型 + ");\n";
		}
		else {
			m_Code += name + " = " + DEF_S(f_JIT_位运算U)"(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + 运算类型 + ");\n";
		}
		
	}
	m_Code += m_ReleaseCode;
	m_Code += "}\n";

	if (f_prop_Bool(m_是否改变原数据)) {
		f_get输出插座(1)->f_setCode(socket1->f_getCode(0));
	}
	else {
		f_get输出插座(1)->f_setCode(name);
	}
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (创建数组) {
			if (f_prop_Bool(m_是否改变原数据)) {
			
			}
			else {
				m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(name);
			}
		}
		return "";
	}
	if (创建数组) {
		if (f_prop_Bool(m_是否改变原数据)) {
		}
		else {
			释放 += f_代码构建_销毁数组(name);
		}
	}
	return m_Code;
}

void C_位运算节点::f_getStr(std::vector<std::vector<std::wstring>>& 文本) {

}

void C_位运算节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_0, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
			下一次读取数据指针 = f_prop_Load(m_是否改变原数据, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_位运算节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);
	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_计算方式, 块);
	f_prop_Save(m_是否改变原数据, 块);

	文件块.m_data = 块->ptr_userData;
	文件块.m_字节数 = 块->count;
	f_file_保存文件块(f, 文件块);
	f_core_array_free((S_Array*)块);
}

void C_位运算节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
	const C_位运算节点* 组合计算节点 = dynamic_cast<const C_位运算节点*>(node);
	if (组合计算节点) {
		f_prop_enum(m_计算方式) = f_prop_enum(组合计算节点->m_计算方式);
		f_prop_Bool(m_是否改变原数据) = f_prop_Bool(组合计算节点->m_是否改变原数据);
	}
}

C_节点基类* f_node_创建位运算节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_位运算节点(ctx);
}

C_节点基类* f_node_加载位运算节点(S_设备环境& ctx, FILE* f) {
	C_位运算节点* node = new C_位运算节点(ctx);
	return node;
}

void f_node_保存位运算节点(C_节点基类* n, FILE* f) {
	C_位运算节点* node = dynamic_cast<C_位运算节点*>(n);
}





C_回写节点::C_回写节点(S_设备环境& ctx) : C_节点基类(DEF_回写节点) {
	m_Ctx = ctx;
	m_Name = L"赋值";

	C_插座基类* socket;
	DEF_创建引用插座_I(L"写入源");
	DEF_创建引用插座_I(L"写入值");

	DEF_创建引用插座_O(L"out");

}

C_回写节点::~C_回写节点() {
}

std::string C_回写节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";
	auto 接入的数据类型1 = f_get输入插座(1)->f_get接入的数据类型();
	auto 接入的数据类型2 = f_get输入插座(2)->f_get接入的数据类型();

	
	//S_Vec3Array a, b;
	//f_array_v3赋值<float32>(&a, &b);
	

	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, 接入的数据类型1);
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, 接入的数据类型1);
	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, 接入的数据类型1);

	auto* inSocket1 = f_get输入插座(1);
	auto* inSocket2 = f_get输入插座(2);

	
	if (inSocket1->f_isLink() && inSocket2->f_isLink()) {
		m_Code += "{\n";

		if (f_代码构建_是否为数组(接入的数据类型1)) {
			//f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I8);
			m_Code += inSocket1->f_构建变量代码(0);
			m_Code += inSocket2->f_构建变量代码(0);

			switch (接入的数据类型1) {
				case E_值类型::e_Type_Vec2_1D:
				case E_值类型::e_Type_iVec2_1D:
					m_Code += DEF_S(f_array_v2赋值<float32>)"(" + inSocket1->f_getCode(0) + ", " + inSocket2->f_getCode(0) + ");\n";
					break;
				case E_值类型::e_Type_Vec3_1D:
				case E_值类型::e_Type_iVec3_1D:
					m_Code += DEF_S(f_array_v3赋值<float32>)"(" + inSocket1->f_getCode(0) + ", " + inSocket2->f_getCode(0) + ");\n";
					break;
				default:
					m_Code += DEF_S(f_array_赋值)"(" + inSocket1->f_getCode(0) + ", " + inSocket2->f_getCode(0) + ");\n";
					break;
			}
			
		}
		else {
			switch (inSocket1->m_Type) {
				case E_值类型::e_Type_I8_1D:
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I8);
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I8); break;
				case E_值类型::e_Type_F32_1D:
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32); break;
				case E_值类型::e_Type_I32_1D:
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I32);
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I32); break;
				case E_值类型::e_Type_UI32_1D:
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_UI32);
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_UI32); break;
				case E_值类型::e_Type_Vec2_1D:
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Vec2);
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec2); break;
				case E_值类型::e_Type_Vec3_1D:
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_Vec3);
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_Vec3); break;

				case E_值类型::e_Type_iVec2_1D:
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_iVec2);
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_iVec2); break;
				case E_值类型::e_Type_iVec3_1D:
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_iVec3);
					f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_iVec3); break;

				default:
					//std::cout<< "error: 赋值节点 - 输入类型错误" << std::endl;
					break;
			}


			inSocket1 = f_get输入插座(1);
			inSocket2 = f_get输入插座(2);


			

			//m_Code += f_get输入插座(2)->f_构建变量代码();
			m_Code += inSocket1->f_构建变量代码(0);
			m_Code += inSocket2->f_构建变量代码(0);



			auto 源值 = inSocket2->f_getCode(0);

			switch (inSocket1->m_Type) {
				case E_值类型::e_Type_Vec2:
					switch (inSocket2->m_Type) {
						case E_值类型::e_Type_Vec4:
						case E_值类型::e_Type_iVec4:
						case E_值类型::e_Type_iVec3:
						case E_值类型::e_Type_iVec2:
						case E_值类型::e_Type_Vec3:
						case E_值类型::e_Type_Vec2:
							m_Code += inSocket1->f_getCode(0) + " = {(float32)(" + 源值 + ").x, " + "(float32)(" + 源值 + ").y }; \n";
							break;
						default:
							goto To_直接赋值;
					}
					break;
				case E_值类型::e_Type_Vec3:
					switch (inSocket2->m_Type) {
						case E_值类型::e_Type_Vec4:
						case E_值类型::e_Type_iVec4:
						case E_值类型::e_Type_iVec3:
						case E_值类型::e_Type_Vec3:
							m_Code += inSocket1->f_getCode(0) + " = {(float32)(" + 源值 + ").x, " + "(float32)(" + 源值 + ").y, " + "(float32)(" + 源值 + ").z }; \n";
							break;
						default:
							goto To_直接赋值;
					}
					break;
				case E_值类型::e_Type_iVec2:
					switch (inSocket2->m_Type) {
						case E_值类型::e_Type_Vec4:
						case E_值类型::e_Type_iVec4:
						case E_值类型::e_Type_iVec3:
						case E_值类型::e_Type_iVec2:
						case E_值类型::e_Type_Vec3:
						case E_值类型::e_Type_Vec2:
							m_Code += inSocket1->f_getCode(0) + " = {(int32)(" + 源值 + ").x, " + "(int32)(" + 源值 + ").y }; \n";
							break;
						default:
							goto To_直接赋值;
					}
					break;
				case E_值类型::e_Type_iVec3:
					switch (inSocket2->m_Type) {
						case E_值类型::e_Type_Vec4:
						case E_值类型::e_Type_iVec4:
						case E_值类型::e_Type_iVec3:
						case E_值类型::e_Type_Vec3:
							m_Code += inSocket1->f_getCode(0) + " = {(int32)(" + 源值 + ").x, " + "(int32)(" + 源值 + ").y, " + "(int32)(" + 源值 + ").z }; \n";
							break;
						default:
							goto To_直接赋值;
					}
					break;
				default:
				To_直接赋值:
					m_Code += inSocket1->f_getCode(0) + " = " + 源值 + ";\n";
			}
		
		}
		m_Code += m_ReleaseCode;
		m_Code += "}\n";

		f_get输出插座(1)->f_setCode(inSocket1->f_getCode(0));
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_插座Type_引用数据);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_插座Type_引用数据);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_插座Type_引用数据);
	
		f_get输出插座(1)->f_setCode(m_Code);
	}

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		return "";
	}
	return m_Code;
}

void C_回写节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	auto 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		//f_prop_Load(m_反向, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_回写节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));
	//f_prop_Save(m_反向, 块);

	文件块.m_data = 块->ptr_userData;
	文件块.m_字节数 = 块->count;
	f_file_保存文件块(f, 文件块);
	f_core_array_free((S_Array*)块);
}

C_节点基类* f_node_创建回写节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_回写节点(ctx);
}

C_节点基类* f_node_加载回写节点(S_设备环境& ctx, FILE* f) {
	C_回写节点* node = new C_回写节点(ctx);
	return node;
}

void f_node_保存回写节点(C_节点基类* n, FILE* f) {
	C_回写节点* node = dynamic_cast<C_回写节点*>(n);
}




C_逻辑计算节点::C_逻辑计算节点(S_设备环境& ctx) : C_节点基类(DEF_逻辑计算节点) {
	m_Ctx = ctx;
	m_Name = L"逻辑运算";

	C_插座基类* socket;
	DEF_创建F32插座_I(L"源1", 0);
	DEF_创建F32插座_I(L"源2", 0);

	DEF_创建I8插座_O(L"真", 0);
	//DEF_创建I8插座_O(L"假", 0);


	m_计算方式 = f_alloc_EnumProp(nullptr, {
		//	0			1			 2		      3		
		{L">", ""}, {L"<", ""},  {L">=", ""}, {L"<=", ""},
		
		//	4			5			 6			  7			  8				
		{L"==", ""}, {L"!=", ""}, {L"&&", ""}, {L"||", ""}, //{L"|", ""}, {L"&", ""}, {L"^", ""},
		//	22			23			24			25			26				27				28				29				30			31				32
		//{L"=", ""}, {L"+=", ""}, {L"-=", ""}, {L"*=", ""}, {L"/=", ""}, { L"%=", "" }, { L"<<=", "" }, { L">>=", "" }, { L"&=", "" }, { L"^=", "" }, { L"|=", "" }

		//	22			23			24			25			26				27				28				29				30			31				32
		//{L"=", ""}, {L"+=", ""}, {L"-=", ""}, {L"*=", ""}, {L"/=", ""}, { L"%=", "" }, { L"<<=", "" }, { L">>=", "" }, { L"&=", "" }, { L"^=", "" }, { L"|=", "" }

		},
		L"计算方式",
		0,
		nullptr
		);
	m_计算方式.m_私有 = true;
}

C_逻辑计算节点::~C_逻辑计算节点() {
	f_prop_Release(m_计算方式);
}

std::string C_逻辑计算节点::f_编译(C_节点基类* rn, std::string& 声明, std::vector<std::string>& 定义, std::string& 释放) {
	m_Code = "";
	m_ReleaseCode = "";
	std::string name = f_getName();

	C_节点树* rt = f_getThis节点树();
	std::string 运算符;



	bool 创建数组 = false;
	bool 创建浮点 = false;
	auto* socket1 = f_get输入插座(1);
	auto* socket2 = f_get输入插座(2);

	auto 接入的数据类型1 = socket1->f_get接入的数据类型();
	auto 接入的数据类型2 = socket2->f_get接入的数据类型();

	if (!socket1->f_isLink() && !socket1->f_isLink()) {
		创建数组 = false;
	}
	else {
		switch (接入的数据类型1) {
			case E_值类型::e_Type_F32_1D:
			case E_值类型::e_Type_I8_1D:
			case E_值类型::e_Type_I32_1D:
			case E_值类型::e_Type_UI32_1D:
				创建数组 = true;
				break;
		}
		switch (接入的数据类型2) {
			case E_值类型::e_Type_F32_1D:
			case E_值类型::e_Type_I8_1D:
			case E_值类型::e_Type_I32_1D:
			case E_值类型::e_Type_UI32_1D:
				创建数组 = true;
				break;
		}
	}

	if (f_代码构建_是否为单值浮点(接入的数据类型1) || f_代码构建_是否为单值浮点(接入的数据类型2)) {
		创建浮点 = true;
	}

	
	if (创建数组) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32_1D);
		//if (创建浮点) {
		//	
		//}
		//else {
		//	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_I32_1D);
		//	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I32_1D);
		//}
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I8_1D);

		m_Code += DEF_S(S_I8Array*)" " + name + ";\n";
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_F32);
		//if (创建浮点) {
		//	
		//}
		//else {
		//	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_I32);
		//	f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 2, E_值类型::e_Type_I32);
		//}
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_I8);

		m_Code += DEF_S(int8)" " + name + ";\n";
	}
	socket1 = f_get输入插座(1);
	socket2 = f_get输入插座(2);


	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	m_Code += socket2->f_构建变量代码(0);

	auto s1Code = socket1->f_getCode(0);
	auto s2Code = socket2->f_getCode(0);

	if (s1Code.empty() || s2Code.empty()) {
		m_编译成功 = false;
	}

	auto 计算方式 = f_代码构建_属性变量(m_计算方式, f_getThis节点树());
	if (创建数组) {
		m_Code += name + " = " + f_代码构建_创建Array(E_值类型::e_Type_I8_1D, "1");
		m_Code += DEF_S(f_JIT_Fn_逻辑计算m);
	}
	else {
		m_Code += DEF_S(f_JIT_Fn_逻辑计算);
	}
	m_Code += "(" + socket1->f_getCode(0) + ", " + socket2->f_getCode(0) + ", " + name + ", " + 计算方式 + ");\n";

	m_Code += m_ReleaseCode;
	m_Code += "}\n";
	

	f_get输出插座(1)->f_setCode(name);
	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;

		if (创建数组) {
			m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(name);
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(name);
	}
	return m_Code;
}

void C_逻辑计算节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;
		if (f_file_版本对比(文件块, S_节点数据::g_低版本号_1, S_节点数据::g_文件版本号)) {
			下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
		}
	}
	free(文件块.m_data);
}

void C_逻辑计算节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_计算方式, 块);

	文件块.m_data = 块->ptr_userData;
	文件块.m_字节数 = 块->count;
	f_file_保存文件块(f, 文件块);
}

void C_逻辑计算节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
	const C_逻辑计算节点* 组合计算节点 = dynamic_cast<const C_逻辑计算节点*>(node);
	if (组合计算节点) {
		f_prop_enum(m_计算方式) = f_prop_enum(组合计算节点->m_计算方式);
		//f_prop_Bool(m_是否改变原数据) = f_prop_Bool(组合计算节点->m_是否改变原数据);
	}
}

C_节点基类* f_node_创建逻辑计算节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_逻辑计算节点(ctx);
}

C_节点基类* f_node_加载逻辑计算节点(S_设备环境& ctx, FILE* f) {
	C_逻辑计算节点* node = new C_逻辑计算节点(ctx);
	return node;
}

void f_node_保存逻辑计算节点(C_节点基类* n, FILE* f) {
	C_逻辑计算节点* node = dynamic_cast<C_逻辑计算节点*>(n);
}




C_单目计算节点::C_单目计算节点(S_设备环境& ctx) : C_节点基类(DEF_单目计算节点) {
	m_Ctx = ctx;
	m_Name = L"逻辑运算";

	C_插座基类* socket;
	DEF_创建F32插座_I(L"源1", nullptr);
	DEF_创建F32插座_O(L"结果", nullptr);


	m_计算方式 = f_alloc_EnumProp(nullptr, {
		//	0			1					
		{L"符号", ""}, {L"!", ""}, 
		//	2			3
		{L"++", ""}, {L"--", ""},
		//{L"!", ""}, //{L"", ""},
		},
		L"计算方式",
		0,
		nullptr
		);
	m_计算方式.m_私有 = true;
}

C_单目计算节点::~C_单目计算节点() {
	f_prop_Release(m_计算方式);
}

bool C_单目计算节点::f_update() {
	auto& v = DEF_F32插座数据(f_get输入插座(1));
	auto& r = DEF_F32插座数据(f_get输出插座(1));

	switch (f_prop_enum(m_计算方式)) {
	case 0:
		r = sign(v);
		break;

	case 1:
		r = !v;
		break;

	case 2:
		r += 1;
		break;

	case 3:
		r -= 1;
		break;
	default:
		break;
	}
	return false;
}

std::string C_单目计算节点::DEF_节点编译函数 {
	m_Code = "";
	m_ReleaseCode = "";
	auto name = f_getName();

	bool 创建数组 = false;

	auto* socket1 = f_get输入插座(1);
	//auto* socket2 = f_get输入插座(2);
	auto type = socket1->f_get接入的数据类型();

	switch (type) {
		case E_值类型::e_Type_I8_1D:
		case E_值类型::e_Type_I32_1D :
		case E_值类型::e_Type_UI32_1D:
		case E_值类型::e_Type_F32_1D:
			创建数组 = true;
			break;
		default:
			break;
	}

	if (创建数组) {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32_1D);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32_1D);

		m_Code = DEF_S(S_F32Array*)" " + name + ";\n";
	}
	else {
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输入, 1, E_值类型::e_Type_F32);
		f_su_切换后端插座类型(this, E_插座方向::e_插座Type_输出, 1, E_值类型::e_Type_F32);

		m_Code = DEF_S(float32)" " + name + ";\n";
	}
	
	m_Code += "{\n";
	m_Code += socket1->f_构建变量代码(0);
	if (创建数组) {
		std::cout<<name << ":error 没有实现单目运算"<<std::endl;
	}
	else {
		m_Code += "switch (" + f_代码构建_属性变量(m_计算方式, f_getThis节点树()) + ") {\n";
		m_Code += "case 0: " + name + " = sign(" + socket1->f_getCode(0) + "); break;\n";
		m_Code += "case 1: " + name + " = !(" + socket1->f_getCode(0) + "); break;\n";
		m_Code += "case 2: " + name + " = (" + socket1->f_getCode(0) + ") + 1; break;\n";
		m_Code += "case 3: " + name + " = (" + socket1->f_getCode(0) + ") - 1; break;\n";
		m_Code += "}\n";
	}
	m_Code += m_ReleaseCode;
	m_Code += "}\n";


	f_get输出插座(1)->f_setCode(name);

	if (m_区域父节点) {
		m_区域父节点->m_Code += m_Code;
		if (创建数组) {
			m_区域父节点->m_ReleaseCode += f_代码构建_销毁数组(name);
		}
		return "";
	}
	if (创建数组) {
		释放 += f_代码构建_销毁数组(name);
	}
	return m_Code;
}

void C_单目计算节点::f_getStr(std::vector<std::vector<std::wstring>>& 文本) {
	auto& r = DEF_F32插座数据(f_get输出插座(1));
	std::vector<std::wstring> 输出(2);
	输出[0] = m_Name;
	输出[1] = f_浮点数值转宽字符串(r);
	文本.push_back(输出);
}

void C_单目计算节点::f_读取(FILE* f) {
	C_节点基类::f_读取(f);
	S_文件块 文件块 = f_file_读取文件块(f);
	if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_节点实例属性) {
		const uint8* 下一次读取数据指针 = 文件块.m_data;

		下一次读取数据指针 = f_prop_Load(m_计算方式, 下一次读取数据指针);
	}
	free(文件块.m_data);
}

void C_单目计算节点::f_写入(FILE* f) {
	C_节点基类::f_写入(f);

	auto 文件块 = f_file_构建文件块信息(E_节点工程文件块类型::e_工程文件块_节点实例属性, S_节点数据::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_prop_Save(m_计算方式, 块);

	文件块.m_data = 块->ptr_userData;
	文件块.m_字节数 = 块->count;
	f_file_保存文件块(f, 文件块);
	f_core_array_free((S_Array*)块);
}

void C_单目计算节点::f_Copy(const C_节点基类* node) {
	C_节点基类::f_Copy(node);
	f_prop_enum(m_计算方式) = f_prop_enum(dynamic_cast<const C_单目计算节点*>(node)->m_计算方式);
}

C_节点基类* f_node_创建单目计算节点(S_设备环境& ctx, C_节点树* 子节点树) {
	return new C_单目计算节点(ctx);
}

C_节点基类* f_node_加载单目计算节点(S_设备环境& ctx, FILE* f) {
	C_单目计算节点* node = new C_单目计算节点(ctx);
	return node;
}

void f_node_保存单目计算节点(C_节点基类* n, FILE* f) {
	C_回写节点* node = dynamic_cast<C_回写节点*>(n);
}







